<?php
// +----------------------------------------------------------------------
// | UCToo [ Universal Convergence Technology ]
// +----------------------------------------------------------------------
// | Copyright (c) 2014-2017 http://uctoo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Patrick <contact@uctoo.com>
// +----------------------------------------------------------------------

namespace app\mpbase\controller;

use think\Controller;
use think\Request;
use com\TPWechat;
use com\wxpay\database\WxPayUnifiedOrder;
use com\wxpay\JsApiPay;
use com\wxpay\NativePay;
use com\wxpay\WxPayApi;
use com\wxpay\WxPayConfig;
use app\mpbase\controller\PayNotifyCallBack;
use app\common\model\Order;
use think\Log;
use com\wxapp\wxBizDataCrypt;
use think\session;

/**
 * 微信小程序消息推送控制器，启用并设置消息推送配置后，用户发给小程序的消息以及开发者需要的事件推送，都将被微信转发至该服务器地址中
 * 主要获取和反馈微信小程序平台的数据，分析用户交互和系统消息分发。
 */
class Wxapp extends Controller {

    protected $weObj;          //自动注入的wechat SDK实例

    //TP5 的架构方法绑定（属性注入）的对象
    public function __construct(TPWechat $weObj)
    {
        $this->weObj = $weObj;
        trace('__construct in Mpbase','info');
        trace($weObj,'info');
        parent::__construct();
    }

     /**
     * 微信消息接口入口
     * 所有发送到微信的消息都会推送到该操作
     * 所以，微信公众平台后台填写的api地址则为该操作的访问地址
     * 在mp.weixin.qq.com 开发者中心配置的 URL(服务器地址)  http://域名/index.php/mpbase/weixin/index/mp_id/member_public表的mp_id.html
     */
	public function onLogin($mp_id) {

        //设置当前上下文的公众号mp_id
        $code = input('code');
        trace($mp_id,'onLogin_mp_id');
        trace($code,'onLogin_code');
        $appinfo = get_mpid_appinfo($mp_id);
        $json = $this->weObj->getWxappSession($code);
        trace($json,'onLogin_json');
        if (!$json) {
            return false;
        }

        $FromUserName = $openid = $json['openid'];
        $session_key = $json['session_key'];

        //将小程序用户信息保存至ucuser表，如果已有则不做任何操作，没有则新建一个小程序用户
        $map['openid'] = $openid;
        $map['mp_id'] = $mp_id;
        $ucuser = model('Ucuser');
        $data = $ucuser->where($map)->find();
        trace($data,'data');
        if(!$data){                                             //公众号没有这个粉丝信息，就注册一个
            $mid = $ucuser->registerUser( $map['mp_id'] ,$map['openid']);    //微信粉丝表ucuser表的mid字段
        }else{
            $mid = $data['mid'];
        }
        //保存微信log
        if (config('app_debug')) { // 是否开发者模式
            addWeixinLog ( '', Request::instance()->request(false),$mp_id, $mid ,$appinfo['appid'],$FromUserName,'wxappSession');
        }
        //生成3rd_session真随机数
        $session_3rd = bin2hex(random_bytes(16));
        trace($session_3rd,'after_initUcuser');
        //以3rd_session为key,session_key+openid为value，写入session存储
        Session::set($session_3rd,$session_key.'@'.$openid);
        $se3rd = Session::get($session_3rd);
        trace($se3rd,'after_initUcuser$se3rd');
        $session_key = substr($se3rd,0,strrpos($se3rd,'@'));
        trace($json['session_key'],'after_initUcusersession_key');
        trace($session_key,'after_initUcuser$session_key');
        //将3rd_session返回给小程序端。小程序端应将3rd_session保存至storage，后续用户进入小程序，先从storage读取3rd_session
        //根据3rd_session在session存储中查找合法的session_key和openid
        $ret = ['session_3rd'=>$session_3rd];
        trace(json($ret),'onLogin_end');
        return $ret;
	}

    //与小程序端wx.checkSession方法对应，用于小程序端调用的接口
    public function checkSession(){
        $session_3rd = input('session_3rd');
        trace($session_3rd , 'checkSessionsession_3rd');
        if(empty($session_3rd)){
            return false;
        }
        $se3rd = Session::get($session_3rd);
        trace($se3rd , 'checkse3rd');
        $session_key = substr($se3rd,0,strrpos($se3rd,'@'));
        trace($session_key , 'checkSessionsession_key');
        if (empty ( $session_key )) {
            return false;
        }
        return true;
    }

    //与小程序端wx.getUserInfo方法对应使用，同步小程序用户信息到ucuser表
    public function setUserInfo(){

        $mp_id = input('mp_id');
        $session_3rd = input('session_3rd');
        $rawData = input('rawData');
        $signature = input('signature');
        $encryptedData = input('encryptedData');
        $iv = input('iv');
        trace($mp_id , 'setUserInfosignature2');
        trace($session_3rd , 'setUserInfosignature2');
        trace($rawData , 'setUserInfosignature2');
        trace($signature , 'setUserInfosignature2');
        trace($encryptedData , 'setUserInfosignature2');
        trace($iv , 'setUserInfosignature2');
        $appinfo = get_mpid_appinfo($mp_id);
        $session_key = checkSession();
        if(!$session_key){
            return false;
        }
        //$session_key = substr(session($session_3rd),0,strrpos(session($session_3rd),'_'));
        trace($session_key , 'setUserInfocheckSession');
        $signature2 = sha1( $rawData + $session_key );
        trace($signature2 , 'setUserInfosignature2');
        if ($signature == $signature2) {      //数据正确

        } else {                              //数据错误
            return false;
        }
        $pc = new wxBizDataCrypt($appinfo['appid'], $session_key);
        $errCode = $pc->decryptData($encryptedData, $iv, $data );
        trace($data , 'setUserInfodata');
        if ($errCode == 0) {

        } else {
            return $errCode;
        }
    }

    /**
     * 微信小程序支付统一下单获取支付参数方法
     * 在微信小程序前端需要进行微信支付的地方通过request接口调用https://www.huaict.com/mpbase/wxapp/wxpay/mp_id/公众号表mp_id字段/id/
     * id参数带上order表的order_id参数请求此地址即可。
     * @return json
     */
    public function wxpay($id)
    {
        $orderData = Order::get(['order_id'=>$id]);
        trace($orderData,'wxpayorder');
        $mp_id = $params['mp_id'] = $map['mp_id'] = get_mpid();
        $appinfo = get_mpid_appinfo ( $params ['mp_id'] );   //获取公众号信息
        trace($mp_id,'info');
        //        $mid = get_ucuser_mid();   //获取粉丝用户mid，一个神奇的函数，没初始化过就初始化一个粉丝
        $cfg = array(
            'APPID'     => $appinfo['appid'],
            'MCHID'     => $appinfo['mchid'],
            'KEY'       => $appinfo['mchkey'],
            'APPSECRET' => $appinfo['secret'],
            'NOTIFY_URL' => $appinfo['notify_url'],
        );
        WxPayConfig::setConfig($cfg);

        if (isset($id) && $id != 0) {
            //获取用户openid
            $tools = new JsApiPay();
            trace($tools,'wxpayJsApiPay');
            //统一下单
            $input = new WxPayUnifiedOrder();
            $input->setBody($orderData->product_name);
            $input->setAttach($orderData->product_sku);
            $input->setOutTradeNo($orderData->order_id);  //建议默认的预支付交易单商户订单号由date("YmdHis").'_'.order_id组成
            $input->setTotalFee($orderData->order_total_price);
            $input->setTimeStart(date("YmdHis"));
            $input->setTimeExpire(date("YmdHis", time() + 600));
            $input->setGoodsTag("Reward");
            $input->setNotifyUrl($appinfo['notify_url']);
            trace($input,'wxpaynotify_url');
            $input->setTradeType("JSAPI");
            $input->setOpenid($orderData->buyer_openid);
            $order = WxPayApi::unifiedOrder($input);

            $jsApiParameters = $tools->getJsApiParameters($order);
            trace($order,'wxpayorder');
            trace($jsApiParameters,'wxpayjsApiParameters');
            trace($orderData,'wxpayorderData');
            return json($jsApiParameters);
        }
    }

}